package org.seckill.service;

import com.sun.xml.internal.bind.v2.TODO;
import org.seckill.dao.DemoMapper;
import org.seckill.dao.RedisDao;
import org.seckill.dao.SeckillMapper;
import org.seckill.dao.SuccessKilledMapper;
import org.seckill.dto.Exposer;
import org.seckill.dto.SeckillExecution;
import org.seckill.entity.Demo;
import org.seckill.entity.Seckill;
import org.seckill.enums.SeckillStateEnum;
import org.seckill.exception.RepeatSeckillException;
import org.seckill.exception.SeckillCloseException;
import org.seckill.exception.SeckillException;
import org.seckill.page.PageQueryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2017-8-12.
 */
@Service("seckillServiceImp")
public class SeckillServiceImp implements SeckillService {

    //秒杀活动的范围
    private final int SECKILL_LIST_LOW = 0;
    private final int SECLKILL_LIST_UP = 4;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //MD5盐
    private final String salt = "345&*^khsa648$DKhd*13oSDK54+)&HE?sd>soke";

    @Autowired
    private SeckillMapper seckillMapper;

    @Autowired
    private SuccessKilledMapper successKilledMapper;

    @Autowired
    private RedisDao redisDao;

    @Autowired
    private DemoMapper demoMapper;

    public int totalRows() {
        return seckillMapper.selectTotalRows();
    }

    public Seckill findSeckillById(Long seckillId) {
        Seckill seckill;

        seckill = redisDao.getSeckill(seckillId);

        if(seckill == null) {
            seckill = seckillMapper.selectByPrimaryKey(seckillId);
            redisDao.putSeckill(seckill);
        }

        return seckill;
    }

    public PageQueryBean getPageList(PageQueryBean pageQueryBean) {

        int count = totalRows();

        if(count > 0) {
            PageQueryBean pageResult = new PageQueryBean();

//        int pageSize = pageQueryBean.getPageSize();
//        int startRow = pageQueryBean.getStartRow();
            List<Seckill> seckillList = seckillMapper.selectByPage(pageQueryBean);

            //pageBean跟前端返回  只需要设置四个参数 pageSize totalRows currentPage items
            pageQueryBean.setCurrentPage(pageQueryBean.getCurrentPage());
            pageQueryBean.setTotalRows(count);
            pageQueryBean.setPageSize(pageQueryBean.getPageSize());

            pageQueryBean.setItems(seckillList);
        }
        return pageQueryBean;
    }
    public List<Seckill> getSeckillList() {

        List<Seckill> seckillList = seckillMapper.selectAll(SECKILL_LIST_LOW,SECLKILL_LIST_UP);

        return seckillList;
    }

    public Exposer exportSeckillUrl(Long seckillId) {
        //Seckill seckill = seckillMapper.selectByPrimaryKey(seckillId);

        Seckill seckill;
        seckill = redisDao.getSeckill(seckillId);
        if(seckill == null) {
            seckill = seckillMapper.selectByPrimaryKey(seckillId);
            if(seckill == null) {
                return new Exposer(false,seckillId);
            }else {
                redisDao.putSeckill(seckill);
            }
        }

        Date startTime = seckill.getStartTime();
        Date endTime = seckill.getEndTime();

        Date nowTime = new Date();
        //活动未开启
        if(nowTime.getTime() < startTime.getTime() || nowTime.getTime() > endTime.getTime()) {
            return new Exposer(false,seckillId,nowTime.getTime(),startTime.getTime(),endTime.getTime());
        }
        String md5 = getMd5(seckillId);
        return new Exposer(true,md5,seckillId);
    }

    @Transactional
    public SeckillExecution executeSeckill(Long seckillId, String md5, Long userPhone) {

        try {
            if(md5 == null || !md5.equals(getMd5(seckillId))) {
                throw new SeckillException("seckill data rewrite");
            }

            int i = successKilledMapper.InsertSuccessKilled(seckillId, userPhone);
                if(i <= 0) {
                    throw new RepeatSeckillException("repeat seckill");
                }else{
                int reduceNumber = seckillMapper.reduceNumber(seckillId, new Date());

                if(reduceNumber <= 0) {
                    throw new SeckillCloseException("seckill is closed");
                }else{
                    return new SeckillExecution(seckillId,SeckillStateEnum.SUCCESS);
                }
            }
        }catch (RepeatSeckillException e){
            throw e;
        }catch (SeckillCloseException e){
            throw e;
        }catch (SeckillException e) {
            logger.error(e.getMessage(),e);
            throw new SeckillException("seckill inner error" + e.getMessage());
        }
    }

    public List<Demo> searchList(String text) {

        List<Demo> demos = demoMapper.selectByLike(text);

        return demos;
    }


    public String getMd5(Long seckillId) {
        String base = seckillId +"/" + salt;
        String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
        return md5;
    }

}
